package com.mec.taskassign.controller;

import com.mec.taskassign.algorithm.OpsRoute;
import com.mec.taskassign.algorithm.OpsRouteNoReturn;
import com.mec.taskassign.model.Place;
import com.mec.taskassign.service.PlaceService;
import com.mec.taskassign.utils.CommonUtils;
import com.mec.taskassign.utils.ResponseResult;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/task-assign/single-route-plan")
@CrossOrigin
public class SingleCarTaskAssignController {

    //变量注入不推荐
    @Autowired
    private PlaceService placeService;

    @Autowired
    private CommonUtils commonUtils;

    @Value(value = "${common-values.script-path}")
    private String test;

//    @Autowired
//    private CommonValues commonValues;
//
//    @RequestMapping("/testing")
//    public String testing(){
//        System.out.println(commonValues.scriptPath);
//        System.out.println(commonValues.carSpeed + 1.24);
//        return test;
//    }




    // 所有任务
    @RequestMapping("/fp")
    public ResponseResult findplace(@RequestParam(required=false,defaultValue="1") int page,
                                    @RequestParam(required=false,defaultValue="30") int limit
    ){

        // 添加分页(读出2+1+0）
        List<Place> datas=placeService.queryAllDataFromTable(page,limit);
        //这个countx是总数据量，不是获取的datas量，为了分页用
        int countx=placeService.queryAllCount();
        //layui数据表格  code要为0，msg要为空
        return ResponseResult.success("",datas,countx,0);
    }
    //根据搜索框给表格传递数据
    @RequestMapping("/queryPlacesBySearchBox")
    public ResponseResult queryPlacesBySearchBox(@RequestParam(required=false,defaultValue="1") int page,
                                         @RequestParam(required=false,defaultValue="30") int limit,
                                         @RequestParam(value = "inputValue") String inputValue){

        List<Place> places = placeService.queryPlacesBySearchBox(page, limit, inputValue);
        int countx=placeService.querySearchCount(inputValue);
        return ResponseResult.success("",places,countx,0);
    }

    // 根据单选过滤器给表格传递数据
    @RequestMapping("/queryPlacesByFilterForm")
    public ResponseResult queryPlacesByFilterForm( @RequestParam(required=false,defaultValue="1") int page,
                                           @RequestParam(required=false,defaultValue="30") int limit,
                                           @RequestParam("filterMode") String filterMode
    ){
        List<Place> formData = new ArrayList<>();
        int countx;     //全部数量，不是分页的数量----用于前端分页
        switch (filterMode) {
            case "all":
                formData = placeService.queryAllDataFromTable(page, limit);
                countx=placeService.queryAllCount();
                break;
            case "obligatory":
                formData = placeService.queryObligatoryForm(page, limit);
                countx=placeService.queryCertainCount(2);
                break;
            case "selectable":
                formData = placeService.querySelectableForm(page,limit);
                countx=placeService.queryCertainCount(1)+placeService.queryCertainCount(2);
                break;
            case "forbidden":
                formData = placeService.queryForbiddenForm(page,limit);
                countx=placeService.queryCertainCount(0);
                break;
            default:
                formData = placeService.queryAllDataFromTable(page, limit);
                countx=placeService.queryAllCount();
                break;
        }
        return ResponseResult.success("",formData,countx,0);
    }


    @RequestMapping("/findAllPlaces")
    public ResponseResult findAllPlaces(){
        return ResponseResult.success("Data retrieving sucess",placeService.findAllPlaces());
    }

    @RequestMapping("/getPlaceById")
    public ResponseResult getPlaceById(@RequestParam Integer id){
        return ResponseResult.success("Data retrieving sucess",placeService.getPlaceById(id));
    }

    //必走任务
    @RequestMapping("/findObligatoryPlaces")
    public ResponseResult findObligatoryPlaces(){
        return ResponseResult.success("Data retrieving sucess",placeService.findObligatoryPlaces());
    }

    //全部可选节点
    @RequestMapping("/findSelectablePlaces")
    public ResponseResult findSelectablePlaces(){
        return ResponseResult.success("Data retrieving sucess",placeService.findSelectablePlaces());
    }

    //增加一个任务
    @RequestMapping("/addTask")
    public ResponseResult addTask(@RequestParam(required = false,defaultValue = "0") Integer id,@RequestParam float jing,@RequestParam float wei,@RequestParam float time,
                                  @RequestParam Integer earn,@RequestParam Integer pri,@RequestParam(required = false,defaultValue = "1") Integer carid,@RequestParam String taskName){
//        System.out.println(place.toString());
        Place place=new Place(id,jing,wei,time,earn,pri,carid,taskName);
        List<Place> allPlaces = placeService.findAllPlaces();
        Integer placeId=0;
        for (int i=1;i<10000;i++){
            //判断这个id是否已经存在
            boolean check=false;
            for (Place onePlace : allPlaces) {
                if (i==onePlace.getId()){
                    check=true;
                    break;
                }
            }
            if (!check){
                placeId=i;
                break;
            }
        }
        place.setId(placeId);
        placeService.addTask(place);
        return ResponseResult.success("Saving operation success. New id is "+placeId);
    }

    // 总任务表格删除任务
    @RequestMapping("/deleteTaskById")
    public ResponseResult deleteTaskById(@RequestParam Integer id){
//        System.out.println(place);
        placeService.delete(id);
        return ResponseResult.success("Task "+id+" successfully deleted");
    }

    //修改任务表格
    @RequestMapping(value = "/reset")
    public ResponseResult reset(@RequestParam Integer id,@RequestParam float jing,@RequestParam float wei,@RequestParam float time,
                                @RequestParam Integer earn,@RequestParam Integer pri,@RequestParam Integer carid,@RequestParam String taskName){
        Place place=new Place(id,jing,wei,time,earn,pri,carid,taskName);
        System.out.println(place.toString());
        placeService.reset(place);
        return ResponseResult.success("Updating operation success");
    }


    /**
     *
     * @param jing
     *      longitude of the place
     * @param wei
     *      latitude of the place
     * @param returnMode
     *      whether or not return to the original place when all positions have been visited
     *      0 for not return/1 for return
     * @return
     *      返回最终路径
     */
    // 单车模式
    @RequestMapping("/opsRoute")
    // 根据geo计算经纬度距离
    public ResponseResult opsRoute(@RequestParam float jing, @RequestParam float wei,@RequestParam Integer returnMode,@RequestParam Integer machineLearningMode) {
        // 全部点
        List<Place> places = new ArrayList<Place>();
        // 必走点
        List<Place> firstpos = new ArrayList<Place>();
        // 最终序列
        List<Place> routeSequence=new ArrayList<Place>();

        //获取所有位置并将不连续的ID空缺补上
        List<Place> place = commonUtils.fillPlacesBlank(placeService.findAllPlaces());

        for(int i=0;i<place.size();i++){
            if(place.get(i).getPri()!=0){
                places.add(place.get(i));
                if(place.get(i).getPri()==2){
                    firstpos.add(place.get(i));
                }
            }
        }
        //System.out.println(places.size());
        // 计算车与地点之间最短距离
        double min = 999999.999;
        int minid = 0;
        for(int i=0;i<places.size();i++){
            GlobalCoordinates source = new GlobalCoordinates(wei, jing);
            GlobalCoordinates target = new GlobalCoordinates(places.get(i).getWei(), places.get(i).getJing());
            double meter1 = commonUtils.getDistanceMeter(source, target, Ellipsoid.Sphere);
            // System.out.println("car:"+meter1);
            if(meter1<min){
                min = meter1;
                minid = places.get(i).getId();
//                System.out.println("minid:"+minid+"min:"+min);
            }
        }
        // 两点之间的距离矩阵two
        float[][] twoDimension = new float[place.size() + 1][place.size() + 1];
        for (int i = 0; i < twoDimension.length; i++) {
            twoDimension[i][i] = 0;
            twoDimension[i][0] = 0;
            twoDimension[0][i] = 0;
        }
//       计算两点之间的距离
        for (int i = 0; i < place.size(); i++) {
            for (int j = i + 1; j < place.size(); j++) {
                GlobalCoordinates source = new GlobalCoordinates(place.get(i).getWei(), place.get(i).getJing());
                GlobalCoordinates target = new GlobalCoordinates(place.get(j).getWei(), place.get(j).getJing());
                double meter1 = commonUtils.getDistanceMeter(source, target, Ellipsoid.Sphere);
//                System.out.println("Sphere坐标系计算结果：" + meter1 + "米");
                twoDimension[i + 1][j + 1] = (float) meter1;
                twoDimension[j + 1][i + 1] = (float) meter1;
            }
        }

        //打印出未处理前的二维矩阵
        for (int i = 0; i < twoDimension.length; i++) {
            for (int j = 0; j < twoDimension[i].length; j++) {
                System.out.print(twoDimension[i][j] + " ");
            }
            System.out.println();
        }

        //如果有机器学习模式，则处理二维矩阵
        if(machineLearningMode==1){
            System.out.println("就是在这里处理的");
            twoDimension = commonUtils.processDistancesWithMachineLearning(twoDimension, placeService.findAllPlaces());
            for (int i = 0; i < twoDimension.length; i++) {
                for (int j = 0; j < twoDimension[i].length; j++) {
                    System.out.print(twoDimension[i][j] + " ");
                }
                System.out.println();
            }
        }

        //确认起点
        Place v0=placeService.getPlaceById(minid);
        //没有必走点
        if(firstpos.size()==0){
            Place[] firstposArray=new Place[0];
            if(returnMode==1){
                //回起点
                OpsRoute opsRoute=new OpsRoute(v0, commonUtils.transferListToArray(places),
                        firstposArray,twoDimension, commonUtils.carSpeed);
                routeSequence=opsRoute.startOps();
            }
            else if(returnMode==0){
                //不回起点
                OpsRouteNoReturn opsRouteNoReturn=new OpsRouteNoReturn(v0,commonUtils.transferListToArray(places),
                        firstposArray,twoDimension, commonUtils.carSpeed);
                routeSequence=opsRouteNoReturn.startOps();
            }

        }
        //必走点刚好是起点并且没有其他必走点
        else if(firstpos.size()==1&&firstpos.get(0).getId()==v0.getId()){
            Place[] firstposArray=new Place[0];
            if(returnMode==1){
                //回起点
                OpsRoute opsRoute=new OpsRoute(v0,commonUtils.transferListToArray(places),
                        firstposArray,twoDimension, commonUtils.carSpeed);
                routeSequence=opsRoute.startOps();
            }
            else if(returnMode==0){
                //不回起点
                OpsRouteNoReturn opsRouteNoReturn=new OpsRouteNoReturn(v0,commonUtils.transferListToArray(places),
                        firstposArray,twoDimension, commonUtils.carSpeed);
                routeSequence=opsRouteNoReturn.startOps();
            }

        }
        //除去起点之外还有必走点
        else {
            if(returnMode==1){
                //回起点
                OpsRoute opsRoute=new OpsRoute(v0,commonUtils.transferListToArray(places),
                        commonUtils.transferListToArray(firstpos),twoDimension, commonUtils.carSpeed);
                routeSequence=opsRoute.startOps();
            }
            else if(returnMode==0){
                //不回起点
                OpsRouteNoReturn opsRouteNoReturn=new OpsRouteNoReturn(v0,commonUtils.transferListToArray(places),
                        commonUtils.transferListToArray(firstpos),twoDimension, commonUtils.carSpeed);
                routeSequence=opsRouteNoReturn.startOps();
            }

        }
//        return routeSequence;
        return ResponseResult.success("Route retrieving success",routeSequence);
    }

    //返回预估时间值 [T_machine, T_noMachine]
    @RequestMapping("/analyzeTime")
    public ResponseResult analyzeTime(@RequestParam("machineSeqIds[]") Integer[] machineSeqIds, @RequestParam("noMachineSeqIds[]") Integer[] noMachineSeqIds){
        //获取所有位置并将不连续的ID空缺补上
        List<Place> place = commonUtils.fillPlacesBlank(placeService.findAllPlaces());
        float[][] twoDimension = new float[place.size() + 1][place.size() + 1];
        for (int i = 0; i < twoDimension.length; i++) {
            twoDimension[i][i] = 0;
            twoDimension[i][0] = 0;
            twoDimension[0][i] = 0;
        }
        //       计算两点之间的距离
        for (int i = 0; i < place.size(); i++) {
            for (int j = i + 1; j < place.size(); j++) {
                GlobalCoordinates source = new GlobalCoordinates(place.get(i).getWei(), place.get(i).getJing());
                GlobalCoordinates target = new GlobalCoordinates(place.get(j).getWei(), place.get(j).getJing());
                double meter1 = commonUtils.getDistanceMeter(source, target, Ellipsoid.Sphere);
//                System.out.println("Sphere坐标系计算结果：" + meter1 + "米");
                twoDimension[i + 1][j + 1] = (float) meter1;
                twoDimension[j + 1][i + 1] = (float) meter1;
            }
        }
        //得到机器学习后的距离矩阵
        twoDimension = commonUtils.processDistancesWithMachineLearning(twoDimension, placeService.findAllPlaces());

        //遍历路径得到总时间
        float totalTime_machine=0;
        float totalTime_noMachine=0;
        float[] timeArray=new float[2];
        for(int i=0;i<machineSeqIds.length-1;i++){
            totalTime_machine+=twoDimension[machineSeqIds[i]][machineSeqIds[i+1]];
        }
        for(int i=0;i<noMachineSeqIds.length-1;i++){
            totalTime_noMachine+=twoDimension[noMachineSeqIds[i]][noMachineSeqIds[i+1]];
        }
        timeArray[0]=totalTime_machine/commonUtils.carSpeed;
        timeArray[1]=totalTime_noMachine/commonUtils.carSpeed;

//        return timeArray;
        return ResponseResult.success("Time analyzing success",timeArray);
    }





}


